package com.hibiscusking.basic.service.impl;

import com.hibiscusking.basic.config.BussinessException;
import com.hibiscusking.basic.constant.BaseConstant;
import com.hibiscusking.basic.dto.PhoneVerificationDto;
import com.hibiscusking.basic.service.VerifyCodeService;
import com.hibiscusking.basic.util.*;
import com.hibiscusking.user.domain.User;
import com.hibiscusking.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    /**
     * @date 2022/10/23 14:15
     * 发送图形验证码
     */
    @Override
    public String pictureVerification(String key) {
        String base64Code = StrUtils.getComplexRandomString(4);
        // 存入redis
        redisTemplate.opsForValue().set(key,base64Code,3, TimeUnit.MINUTES);
        return VerifyCodeUtils.VerifyCode(100,35,base64Code);

    }
    /**
     * @date 2022/10/23 14:15
     * 发送手机验证码
     */
    @Override
    public void sendOutVerification(PhoneVerificationDto dto) {
        // 判断是否是绑定手机号时的验证码
        if("binder".equals(dto.getType())){
            // 判断手机号格式是否正确
            if (!PhoneFormatUtil.isMobileNO(dto.getPhone())) {
                throw new BussinessException("手机号错误");
            }
            // 判断验证码是否是在60秒内发送过,不在则重新发送，并存入redis
            judgeSendMessageTime(redisTemplate,dto);
        } else if("register".equals(dto.getType())){
            // 判断手参数是否正确,判断图像验证码是否正确
            judgeIsNotEmpty(dto);
            // 判断验证码是否是在60秒内发送过,不在则重新发送，并存入redis
            judgeSendMessageTime(redisTemplate,dto);
        } else {
            throw new BussinessException("type类型不正确");
        }
    }
    /**
     * @date 2022/10/23 14:15
     * 判断参数是否正确方法
     */
    private void judgeIsNotEmpty(PhoneVerificationDto dto) {
        if (!PhoneFormatUtil.isMobileNO(dto.getPhone())) {
            throw new BussinessException("手机号错误");
        }
        if (!PhoneFormatUtil.isMobileNO(dto.getImageCodeValue())) {
            throw new BussinessException("图形验证码不能为空");
        }
        if (!PhoneFormatUtil.isMobileNO(dto.getImageCodeKey())) {
            throw new BussinessException("图形验证码的key不能为空");
        }
        String codeKey = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (StringUtils.isBlank(codeKey) || !dto.getImageCodeValue().equalsIgnoreCase(codeKey)){
            throw new BussinessException("验证码错误");
        }
        // 判断手机号是否有被注册过
        User user = userMapper.findUserByPhone(dto.getPhone());
        if (user != null) {
            throw new BussinessException("账号已经有注册");
        }
    }

    /**
     * @date 2022/10/23 9:51
     * 判断发送手机验证码是否是在60秒内发送过,不在则重新发送，并存入redis方法
     */
    private static void judgeSendMessageTime(RedisTemplate redisTemplate,PhoneVerificationDto dto){
        if ("binder".equals(dto.getType())) {
            // 判断验证码是否是在60秒内发送过
            String verfityCode = (String) redisTemplate.opsForValue().get(
                    String.format(BaseConstant.VerfityCodeCons.BINDER_SMSCODE_PHONE,dto.getPhone()));
            if (StringUtils.isNotBlank(verfityCode)) {
                Long expire = redisTemplate.getExpire(String.format(BaseConstant.VerfityCodeCons.BINDER_SMSCODE_PHONE,dto.getPhone()),TimeUnit.MINUTES);
                if (expire >= 4) {
                    throw  new BussinessException("等待60秒后获取短信验证码");
                }
            }
            // 生产验证码
            String randomString = StrUtils.getRandomString(4);
            // 存入redis
            redisTemplate.opsForValue().set(String.format(BaseConstant.VerfityCodeCons.BINDER_SMSCODE_PHONE,dto.getPhone()),randomString,5,TimeUnit.MINUTES);
            log.info(randomString);
            // 发送短信
            // SendInformationUtils.send(dto.getPhone(),randomString);
        } else if("register".equals(dto.getType())){
            // 判断验证码是否是在60秒内发送过
            String verfityCode = (String) redisTemplate.opsForValue().get(
                    String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE,dto.getPhone()));
            if (StringUtils.isNotBlank(verfityCode)) {
                Long expire = redisTemplate.getExpire(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE,dto.getPhone()),TimeUnit.MINUTES);
                if (expire >= 4) {
                    throw  new BussinessException("等待60秒后获取短信验证码");
                }
            }
            // 生产验证码
            String randomString = StrUtils.getRandomString(4);
            // 存入redis
            redisTemplate.opsForValue().set(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE,dto.getPhone()),randomString,5,TimeUnit.MINUTES);
            log.info(randomString);
            // 发送短信
            // SendInformationUtils.send(dto.getPhone(),randomString);
        }

    }
    /**
     * @date 2022/10/23 14:16
     * 发送邮箱验证码
     */
    @Override
    public void  sendOutEmailVerification(String emailKey) {
        String[] k = emailKey.split(":");
        String key = k[0];
        String type = k[1];
        // 验证邮箱格式
        verifyMailbox(key,type);
        // 获取随机验证码
        String emailCode = StrUtils.getComplexRandomString(5);
        // 存入redis
        redisTemplate.opsForValue().set(String.format(BaseConstant.VerfityCodeCons.SEND_VERIFICATION_EMAIL,key),emailCode,5,TimeUnit.MINUTES);
        // 发送邮箱验证码
        if (!MailUtils.sendMail(key, "宠物之家，您本次的邮箱验证码为" + emailCode + "请在5分钟内使用", "宠物之家邮箱验证")) {
            throw new BussinessException("邮件发送错误，请查看邮箱是否正确");
        }
        log.info(emailCode);
    }

    private void verifyMailbox(String key,String type) {
        // 判断邮箱格式是否正确
        if (!CheckEmailUtil.checkEmail(key)) {
            throw new BussinessException("邮箱不正确");
        }
        if (!"0".equals(type) || !"1".equals(type)){
            throw new BussinessException("邮箱类型不正确");
        }
        // 判断邮箱是否有注册过
        if ("0".equals(type)){
            User user = userMapper.findUserByEmail(key);
            if (user != null) {
                throw new BussinessException("邮箱已经注册");
            }
        }

    }
}
